package com.example.springboot01.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springboot01.entity.*;
import com.example.springboot01.entity.Class;
import com.example.springboot01.execs.CustomException;
import com.example.springboot01.mapper.StudentMapper;
import com.example.springboot01.model.LoginStatusModel;
import com.example.springboot01.model.constants.UserType;
import com.example.springboot01.req.PageQueryReq;
import com.example.springboot01.resp.enums.CommonRespEnum;
import com.example.springboot01.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {


    @Resource
    private UserService userService;

    @Resource
    private TeacherClassService classService;

    @Resource
    private ClassService clsService;

    @Resource
    private ProfessorService professorService;


    @Override
    public Student getByUserId(Serializable userId) {
        return this.getOne(new LambdaQueryWrapper<Student>()
                .eq(Student::getUserId, userId)
        );
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addStudent(Student s) {
        User u = new User();
        u.setUsername(s.getStudentNo());
        u.setPassword("88888888");
        u.setUserType(0);
        userService.save(u);

        s.setUserId(u.getId());
        this.save(s);
    }

    @Override
    public List<Student> queryByClass(Integer cId) {
        return this.list(new LambdaQueryWrapper<Student>()
                .eq(Student::getClassId, cId)
        );
    }

    @Override
    public List<Student> queryByClasses(Collection<Integer> cId) {
        if (CollectionUtils.isEmpty(cId)) {
            return new ArrayList<>();
        }
        return this.list(new LambdaQueryWrapper<Student>()
                .in(Student::getClassId, cId)
        );
    }

    @Override
    public IPage<Student> getPage(PageQueryReq pageQueryReq, HttpSession session) {
        IPage<Student> result = new Page<>(pageQueryReq.getCurrent(), pageQueryReq.getSize());
        Object status = session.getAttribute("status");
        if (status == null) {
            throw new CustomException(CommonRespEnum.UNAUTHORIZED);
        } else {
            LoginStatusModel model = (LoginStatusModel) status;
            User user = userService.getById(model.getId());
            Integer userType = user.getUserType();

            if (userType == UserType.TEACHER) {
                List<Integer> classId = classService.queryClassIdByTeacher(model.getId());
                if (!classId.isEmpty()) {
                    result = this.page(result, new LambdaQueryWrapper<Student>().in(Student::getClassId, classId));
                }
            } else {
                result = this.page(result, new LambdaQueryWrapper<Student>());
            }
        }
        return result;
    }

    @Override
    public List<Student> listWithDetail(String search) {
        List<Student> list = this.list(new LambdaQueryWrapper<Student>()
                .likeLeft(StringUtils.hasLength(search), Student::getStudentNo, search)
                .or()
                .likeLeft(StringUtils.hasLength(search), Student::getRealName, search)
        );
        List<Integer> classPks = list.stream().map(Student::getClassId).collect(Collectors.toList());
        List<Integer> profrssorPks = list.stream().map(Student::getProfessorId).collect(Collectors.toList());
        Map<Integer, String> clsMap = new HashMap<>();
        Map<Integer, String> proMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(classPks)) {
            clsMap.putAll(clsService.listByIds(classPks).stream().collect(Collectors.toMap(Class::getId, Class::getName)));
        }

        if (!CollectionUtils.isEmpty(profrssorPks)) {
            proMap.putAll(professorService.listByIds(profrssorPks).stream().collect(Collectors.toMap(Professor::getId, Professor::getName)));
        }

        for (Student student : list) {
            student.setProfessorName(proMap.get(student.getProfessorId()));
            student.setClassName(clsMap.get(student.getClassId()));
        }

        return list;
    }
}
